/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <aarch64-linux-ohos/bits/alltypes.h>
#include <cstdint>
#include <string>
#include <cstdio>
#include <thread>
#include <unistd.h>
#include <vector>

#include <ace/xcomponent/native_interface_xcomponent.h>
#include <hilog/log.h>

#include "manager.h"

namespace NativeXComponentSample {
    Manager Manager::manager_;
    static ArkUI_NativeNodeAPI_1 *nodeAPI;
    enum RefreshState { DropDown = 0, Release = 1, Refreshing = 2, Success = 3 };

    // 下拉刷新头文本
    char pullDownRefreshText[20];
    // 下拉刷新头图片
    char pullDownRefreshImage[128];
    // 下拉刷新中的高度，offsetY超过这个高度，就应该刷新
    int pullDownRefreshHeight = 70;

    // 是否下拉刷新，本来是用来判断显示和隐藏刷新头的,目前没有用到，visibility 不生效
    bool isVisiblePullDown;
    // 刷新头的高度，高度为0,不显示刷新头
    float refreshHeaderHeight = 0;

    // 上拉刷新相关,目前没有用到
    char pullUpLoadText[20];
    char pullUpLoadImage[128];
    int pullUpLoadHeight;
    bool isVisiblePullUpload;


    // 手指按下时Y 不会一直更新，就按下当前点
    int downY;
    // 最新移动时点Y 一直移动就一直更新
    int lastMoveY;
    // 最新移动点和 按下 点 的差值，一直移动就一直更新,list 就会一直出现偏移
    int offsetY;

    // 是否正在刷新
    bool isRefreshing;
    // 是否可以刷新
    bool isCanRefresh;

    // 是否正在加载
    bool isLoading;
    // 是否可以加载
    bool isCanLoadMore;

    Manager::~Manager() {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "~Manager");
        for (auto iter = nativeXComponentMap_.begin(); iter != nativeXComponentMap_.end(); ++iter) {
            if (iter->second != nullptr) {
                // delete iter->second;
                iter->second = nullptr;
            }
        }
        nativeXComponentMap_.clear();
        for (auto iter = nativeNodeMap_.begin(); iter != nativeNodeMap_.end(); ++iter) {
            if (iter->second != nullptr) {
                // delete iter->second;
                iter->second = nullptr;
            }
        }
        nativeNodeMap_.clear();

        for (auto iter = containerMap_.begin(); iter != containerMap_.end(); ++iter) {
            if (iter->second != nullptr) {
                delete iter->second;
                iter->second = nullptr;
            }
        }
        containerMap_.clear();
    }

    void pullRefreshState(NativeXComponentSample::RefreshState state) {
        switch (state) {
        case DropDown: {
            char dropDownText[128] = "下拉刷新";
            std::copy(std::begin(dropDownText), std::end(dropDownText), std::begin(pullDownRefreshText));
            char tmpDownSrc[128] = "pages/common/ic_pull_down_refresh.png";
            std::copy(std::begin(tmpDownSrc), std::end(tmpDownSrc), std::begin(pullDownRefreshImage));

            isCanRefresh = true;
            isRefreshing = false;
            refreshHeaderHeight = 50;
            isVisiblePullDown = true;
            OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "===DropDown==llh==");
            break;
        }
        case Release: {
            char releaseText[128] = "松开刷新";
            std::copy(std::begin(releaseText), std::end(releaseText), std::begin(pullDownRefreshText));
            char tmpDownRefreshSrc[128] = "pages/common/ic_pull_up_refresh.png";
            std::copy(std::begin(tmpDownRefreshSrc), std::end(tmpDownRefreshSrc), std::begin(pullDownRefreshImage));
            isCanRefresh = true;
            isRefreshing = false;
            OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "===Release==llh==");
            break;
        }
        case Refreshing: {
            offsetY = pullDownRefreshHeight;
            char refreshingText[128] = "正在刷新";
            std::copy(std::begin(refreshingText), std::end(refreshingText), std::begin(pullDownRefreshText));
            char refreshingSrc[128] = "pages/common/ic_pull_up_load.gif";
            std::copy(std::begin(refreshingSrc), std::end(refreshingSrc), std::begin(pullDownRefreshImage));

            isCanRefresh = false;
            isRefreshing = true;
            
            OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "===Refreshing==llh==");
            break;
        }
        case Success: {
            offsetY = 0;
            char successText[128] = "刷新成功";
            std::copy(std::begin(successText), std::end(successText), std::begin(pullDownRefreshText));
            char successSrc[128] = "pages/common/ic_succeed_refresh.png";
            std::copy(std::begin(successSrc), std::end(successSrc), std::begin(pullDownRefreshImage));
            isCanRefresh = true;
            isRefreshing = false;
            isVisiblePullDown = false;
            OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "===Success==llh==");
            break;
        }
        default:
            break;
        }
    }

    void touchMovePullRefresh(ArkUI_NodeEvent *event) {
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "touchMovePullRefresh==nodeY===llh=%{public}d",
                     event->touchEvent.actionTouch.nodeY);
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "touchMovePullRefresh==downY===llh=%{public}d",
                     downY);
        offsetY = event->touchEvent.actionTouch.nodeY - downY;
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "touchMovePullRefresh==offsetY===llh=%{public}d",
                     offsetY);
        // 滑动偏移量大于下拉刷新布局高度。
        if (offsetY >= pullDownRefreshHeight) {
            pullRefreshState(Release);
        } else {
            pullRefreshState(DropDown);
        }
    }

    void touchMoveLoadMore(ArkUI_NodeEvent *event) {}


    void closeRefresh(bool isCanRefresh) {
        if (isCanRefresh == true) {
            pullRefreshState(Success);
         //   usleep(1000000);

            refreshHeaderHeight = 0;
        }
    }

    void touchUpPullRefresh() {
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "touchUpPullRefresh==llh===isCanRefresh%{public}d",
                     isCanRefresh);
        if (isCanRefresh == true) {
            offsetY = pullDownRefreshHeight;
            pullRefreshState(Refreshing);
           // usleep(3000000); // 延时（3秒）
           // closeRefresh(true);
        } else {
            closeRefresh(false);
        }
        if (offsetY < 0) {
            offsetY = 0;
            isCanRefresh = false;
        }
    }

    void touchUpLoadMore() {}

    napi_value Manager::CreateNativeNode(napi_env env, napi_callback_info info) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode BEGIN");
        if ((env == nullptr) || (info == nullptr)) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode env or info is null");
            return nullptr;
        }
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 1");
        size_t argCnt = 1;
        napi_value args[1] = {nullptr};
        if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode napi_get_cb_info failed");
        }
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 2");

        if (argCnt != 1) {
            napi_throw_type_error(env, NULL, "Wrong number of arguments");
            return nullptr;
        }
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 3");
        napi_valuetype valuetype;
        if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
            napi_throw_type_error(env, NULL, "napi_typeof failed");
            return nullptr;
        }
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 4");
        if (valuetype != napi_string) {
            napi_throw_type_error(env, NULL, "Wrong type of arguments");
            return nullptr;
        }
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 5");

        char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
        constexpr uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
        size_t length;
        if (napi_get_value_string_utf8(env, args[0], idStr, idSize, &length) != napi_ok) {
            napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
            return nullptr;
        }
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 6");

        auto manager = Manager::GetInstance();
        if (manager == nullptr) {
            return nullptr;
        }
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 7 idStr(%{public}s)", idStr);

        OH_NativeXComponent *component = manager->GetNativeXComponent(idStr);
        if (component == nullptr) {
            return nullptr;
        }
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "OH_ArkUI_GetBasicNodeAPI before");
        nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(OH_ArkUI_GetNativeAPI(ARKUI_NATIVE_NODE, 1));
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "OH_ArkUI_GetBasicNodeAPI after");
        if (nodeAPI != nullptr) {
            if (nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) {
                OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 1");

                OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode column");

                // 最外层 column
                static ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
                ArkUI_NumberValue columnWidth[] = {480};
                ArkUI_AttributeItem columnWidthItem = {columnWidth, 1};
                nodeAPI->setAttribute(column, NODE_WIDTH, &columnWidthItem);
                ArkUI_NumberValue columnHeight[] = {800};
                ArkUI_AttributeItem columnHeightItem = {columnHeight, 1};
                nodeAPI->setAttribute(column, NODE_HEIGHT, &columnHeightItem);
            
                ArkUI_NumberValue colorValue[] = {{.u32 = 0Xffff0000}};
                ArkUI_AttributeItem colorItem = {colorValue, sizeof(colorValue) / sizeof(ArkUI_NumberValue)};
                nodeAPI->setAttribute(column, NODE_BACKGROUND_COLOR, &colorItem);

                // 里面的 list
                OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode list");
                static ArkUI_NodeHandle list = nodeAPI->createNode(ARKUI_NODE_LIST);
                ArkUI_NumberValue listVertical[] = {{.i32 = ARKUI_AXIS_VERTICAL}};
                ArkUI_AttributeItem listVerticalItem = {listVertical, sizeof(listVertical) / sizeof(ArkUI_NumberValue)};
                nodeAPI->setAttribute(list, NODE_LIST_DIRECTION, &listVerticalItem);

                ArkUI_NumberValue listWidth[] = {480};
                ArkUI_AttributeItem listWidthItem = {listWidth, 1};
                nodeAPI->setAttribute(list, NODE_WIDTH, &listWidthItem);

                ArkUI_NumberValue listSpace[] = {{.i32 = 200}};
                ArkUI_AttributeItem listSpaceItem = {listSpace, sizeof(listSpace) / sizeof(ArkUI_NumberValue)};
                nodeAPI->setAttribute(list, NODE_LIST_SPACE, &listSpaceItem);
                ArkUI_NumberValue colorListValue[] = {{.u32 = 0Xff70DB93}};
                ArkUI_AttributeItem colorListItem = {colorListValue,
                                                     sizeof(colorListValue) / sizeof(ArkUI_NumberValue)};
                nodeAPI->setAttribute(list, NODE_BACKGROUND_COLOR, &colorListItem);


                // 刷新头加入最前面listItem
                static ArkUI_NodeHandle row = nodeAPI->createNode(ARKUI_NODE_ROW);
                ArkUI_NumberValue widthRowValue[] = {400};
                ArkUI_AttributeItem widthRowItem = {widthRowValue, 1};
                nodeAPI->setAttribute(row, NODE_WIDTH, &widthRowItem);

                ArkUI_NumberValue rowMargin[] = {0,0,0,200};
                ArkUI_AttributeItem rowMarginItem = {rowMargin,
                                                      sizeof(rowMargin) / sizeof(ArkUI_NumberValue)};
                nodeAPI->setAttribute(row, NODE_MARGIN, &rowMarginItem);

                static ArkUI_NumberValue heightRowValue[] = {float (offsetY)};
                static ArkUI_AttributeItem heightRowItem = {heightRowValue, 1};
                nodeAPI->setAttribute(row, NODE_HEIGHT, &heightRowItem);

                static ArkUI_NodeHandle image = nodeAPI->createNode(ARKUI_NODE_IMAGE);
                static ArkUI_AttributeItem imageItem = {.string = ""};
                nodeAPI->setAttribute(image, NODE_IMAGE_SRC, &imageItem);
                ArkUI_NumberValue imageWidthValue[] = {40};
                ArkUI_AttributeItem imageWidthItem = {imageWidthValue, 1};
                nodeAPI->setAttribute(image, NODE_WIDTH, &imageWidthItem);

                ArkUI_NumberValue imageHeightValue[] = {40};
                ArkUI_AttributeItem imageHeightItem = {imageHeightValue, 1};
                nodeAPI->setAttribute(image, NODE_HEIGHT, &imageHeightItem);


                static ArkUI_NodeHandle textRom = nodeAPI->createNode(ARKUI_NODE_TEXT);
                static ArkUI_AttributeItem textContentItem = {.string = ""};
                ArkUI_NumberValue sizeTextRomValue[] = {20};
                ArkUI_AttributeItem sizeItem = {sizeTextRomValue, 1};
                nodeAPI->setAttribute(textRom, NODE_TEXT_CONTENT, &textContentItem);
                nodeAPI->setAttribute(textRom, NODE_FONT_SIZE, &sizeItem);

                nodeAPI->addChild(row, image);
                nodeAPI->addChild(row, textRom);

                nodeAPI->addChild(column, row);

                const int SIZE = 12;
                struct Subcomponents {
                    char contentValue[20];
                    char imgSrc[128];
                    uint32_t color;
                };
                Subcomponents subcomponents[SIZE] = {
                    {"Text1", "pages/common/icon.png", 0xFFFF0000}, {"Text2", "pages/common/icon.png", 0xFFFFFF00},
                    {"Text3", "pages/common/icon.png", 0xFF0000FF}, {"Text4", "pages/common/icon.png", 0Xff0000ff},
                    {"Text5", "pages/common/icon.png", 0XFFFF0000}, {"Text6", "pages/common/icon.png", 0xFFFFFF00},
                    {"Text7", "pages/common/icon.png", 0xFFFF0000}, {"Text8", "pages/common/icon.png", 0xFFFFFF00},
                    {"Text9", "pages/common/icon.png", 0xFF0000FF}, {"Text10", "pages/common/icon.png", 0Xff0000ff},
                    {"Text11", "pages/common/icon.png", 0XFFFF0000}, {"Text12", "pages/common/icon.png", 0xFFFFFF00},
                };
                for (int32_t i = 0; i < SIZE; i++) {
                    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode listItem%{public}d",
                                 i);
                    ArkUI_NodeHandle listItem = nodeAPI->createNode(ARKUI_NODE_LIST_ITEM);

                    ArkUI_NodeHandle columnListItem = nodeAPI->createNode(ARKUI_NODE_COLUMN);

                    ArkUI_NumberValue columnHeight[] = {100};
                    ArkUI_AttributeItem columnHeightItem = {columnHeight, 1};
                    nodeAPI->setAttribute(columnListItem, NODE_HEIGHT, &columnHeightItem);

                    ArkUI_NumberValue columnWidth[] = {400};
                    ArkUI_AttributeItem columnWidthItem = {columnWidth, 1};
                    nodeAPI->setAttribute(columnListItem, NODE_WIDTH, &columnWidthItem);
                
                    ArkUI_NodeHandle text = nodeAPI->createNode(ARKUI_NODE_TEXT);
                    ArkUI_AttributeItem textContentItem = {.string = subcomponents[i].contentValue};
                    ArkUI_NumberValue sizeValue[] = {40};
                    ArkUI_AttributeItem sizeItem = {sizeValue, 1};
                    nodeAPI->setAttribute(text, NODE_TEXT_CONTENT, &textContentItem);
                    nodeAPI->setAttribute(text, NODE_FONT_SIZE, &sizeItem);

                    ArkUI_NumberValue color[] = {{.u32 = subcomponents[i].color}};// 背景色
                    ArkUI_AttributeItem colorItem = {color, 1};
                    nodeAPI->setAttribute(text, NODE_BACKGROUND_COLOR, &colorItem);

                    ArkUI_NumberValue borderWidth[] = {1, 0, 1, 0}; // 每个columnListItem使用边框
                    ArkUI_AttributeItem borderWidthItem = {borderWidth,
                                                           sizeof(borderWidth) / sizeof(ArkUI_NumberValue)};
                    nodeAPI->setAttribute(columnListItem, NODE_BORDER_WIDTH, &borderWidthItem);
                    ArkUI_NumberValue textBorderWidth[] = {1};
                    ArkUI_AttributeItem textBorderWidthItem = {textBorderWidth,
                                                               sizeof(textBorderWidth) / sizeof(ArkUI_NumberValue)};
                    nodeAPI->setAttribute(text, NODE_BORDER_WIDTH, &textBorderWidthItem);

                    ArkUI_NumberValue borderRadius[] = {10};
                    ArkUI_AttributeItem borderRadiusItem = {borderRadius,
                                                            sizeof(borderRadius) / sizeof(ArkUI_NumberValue)};
                    nodeAPI->setAttribute(text, NODE_BORDER_RADIUS, &borderRadiusItem);

                    ArkUI_NumberValue borderColor[] = {{.u32 = 0xFF0000FF}};
                    ArkUI_AttributeItem borderColorItem = {borderColor,
                                                           sizeof(borderColor) / sizeof(ArkUI_NumberValue)};
                    nodeAPI->setAttribute(text, NODE_BORDER_COLOR, &borderColorItem);
                    nodeAPI->setAttribute(columnListItem, NODE_BORDER_COLOR, &borderColorItem);


                    nodeAPI->addChild(columnListItem, text);
                    nodeAPI->addChild(listItem, columnListItem);
                    nodeAPI->addChild(list, listItem);
                }


                ArkUI_NumberValue edgeEffectValue[] = {{.i32 = ARKUI_EDGE_EFFECT_NONE}, {.i32 = 0}};
                ArkUI_AttributeItem edgeEffectItem = {edgeEffectValue,
                                                      sizeof(edgeEffectValue) / sizeof(ArkUI_NumberValue)};
                nodeAPI->setAttribute(list, NODE_SCROLL_EDGE_EFFECT, &edgeEffectItem);


                nodeAPI->addChild(column, list);
                nodeAPI->registerNodeEvent(column, NODE_TOUCH_EVENT, 1);
                nodeAPI->registerNodeEventReceiver([](ArkUI_NodeEvent *event) {
                    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "type===llh=%{public}d",
                                 event->touchEvent.action);

                    // NODE_ACTION_DOWN = 0;
                    // NODE_ACTION_UP = 1;
                    // NODE_ACTION_MOVE = 2;
                    // NODE_ACTION_CANCEL = 3;

                    if (event->touchEvent.action == 0) {
                        downY = event->touchEvent.actionTouch.nodeY;
                        lastMoveY = event->touchEvent.actionTouch.nodeY;
                        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager",
                                     "action0==nodeY===llh===%{public}d===downY===%{public}d===lastMoveY===%{public}d",
                                     event->touchEvent.actionTouch.nodeY, downY, lastMoveY);
                    } else if (event->touchEvent.action == 1) {

                        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "action1=====llh===%{public}d",
                                     isCanRefresh);
                        if ((isRefreshing == true) || (isLoading == true)) {
                            return;
                        }
                        if (isCanRefresh == true) {
                            // 向下拉后抬起手指进行刷新
                            touchUpPullRefresh();

                            OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager",
                                         "action1===offsetY===llh=%{public}d==refreshHeaderHeight==%{public}f=="
                                         "pullDownRefreshImage==%{public}s==pullDownRefreshText==%{public}s==="
                                         "isVisiblePullDown==%{public}d",
                                         offsetY, refreshHeaderHeight, pullDownRefreshImage, pullDownRefreshText,
                                         isVisiblePullDown);

                            ArkUI_NumberValue offsetArray[] = {0, float(offsetY)};
                            ArkUI_AttributeItem offsetItem = {.value = offsetArray, .size = 2};
                            nodeAPI->setAttribute(list, NODE_OFFSET, &offsetItem);

                            heightRowValue[0].f32 = offsetY;
                            heightRowItem = {heightRowValue, 1};
                            nodeAPI->setAttribute(row, NODE_HEIGHT, &heightRowItem);

                            imageItem = {.string = pullDownRefreshImage};
                            nodeAPI->setAttribute(image, NODE_IMAGE_SRC, &imageItem);


                            textContentItem = {.string = pullDownRefreshText};

                            nodeAPI->setAttribute(textRom, NODE_TEXT_CONTENT, &textContentItem);


                        } else {
                            // 手指往上松开，加载更多
                            //touchUpLoadMore();
                        }

                    } else if (event->touchEvent.action == NODE_ACTION_MOVE) {
                        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager",
                                     "action2==isRefreshing===llh=%{public}d===model.isLoading==%{public}d=",
                                     isRefreshing, isLoading);
                        if ((isRefreshing == true) || (isLoading == true)) {
                            return;
                        }
                        bool isDownPull = (event->touchEvent.actionTouch.nodeY - lastMoveY) > 0 ? true : false;
                        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager",
                                     "action2===isDownPull===llh=%{public}d", isDownPull);
                        if (((isDownPull == true) || (isCanRefresh == true)) && (isCanLoadMore == false)) {
                            // 手指移动，处理下拉刷新。
                            touchMovePullRefresh(event);

                            OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager",
                                         "action2===offsetY===llh=%{public}d==refreshHeaderHeight==%{public}f=="
                                         "pullDownRefreshImage==%{public}s==pullDownRefreshText==%{public}s",
                                         offsetY, refreshHeaderHeight, pullDownRefreshImage, pullDownRefreshText);
                            ArkUI_NumberValue offsetArray[] = {0, float(offsetY)};
                            ArkUI_AttributeItem offsetItem = {.value = offsetArray, .size = 2};
                            nodeAPI->setAttribute(list, NODE_OFFSET, &offsetItem);


                            heightRowValue[0].f32 = offsetY;
                            heightRowItem = {heightRowValue, 1};
                            nodeAPI->setAttribute(row, NODE_HEIGHT, &heightRowItem);

                            imageItem = {.string = pullDownRefreshImage};
                            nodeAPI->setAttribute(image, NODE_IMAGE_SRC, &imageItem);


                            textContentItem = {.string = pullDownRefreshText};

                            nodeAPI->setAttribute(textRom, NODE_TEXT_CONTENT, &textContentItem);


                        } else {
                            // 手指移动，加载更多
                            //touchMoveLoadMore(event);
                        }
                        lastMoveY = event->touchEvent.actionTouch.nodeY;


                    } else if (event->touchEvent.action == 3) {
                    }
                });

                OH_NativeXComponent_AttachNativeRootNode(component, column);
            }
        }
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode  555");
        return nullptr;
    }

    napi_value Manager::UpdateNativeNode(napi_env env, napi_callback_info info) {

        if ((env == nullptr) || (info == nullptr)) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "UpdateNativeNode env or info is null");
            return nullptr;
        }

        size_t argCnt = 1;
        napi_value args[1] = {nullptr};
        if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "UpdateNativeNode napi_get_cb_info failed");
        }

        if (argCnt != 1) {
            napi_throw_type_error(env, NULL, "Wrong number of arguments");
            return nullptr;
        }

        napi_valuetype valuetype;
        if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
            napi_throw_type_error(env, NULL, "napi_typeof failed");
            return nullptr;
        }

        if (valuetype != napi_string) {
            napi_throw_type_error(env, NULL, "Wrong type of arguments");
            return nullptr;
        }

        char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
        constexpr uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
        size_t length;
        if (napi_get_value_string_utf8(env, args[0], idStr, idSize, &length) != napi_ok) {
            napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
            return nullptr;
        }

        auto manager = Manager::GetInstance();
        if (manager == nullptr) {
            return nullptr;
        }

        OH_NativeXComponent *component = manager->GetNativeXComponent(idStr);
        if (component == nullptr) {
            return nullptr;
        }

        if ((env == nullptr) || (info == nullptr || component == nullptr)) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "GetContext env or info is null");
            return nullptr;
        }

        return nullptr;
    }

    napi_value Manager::GetContext(napi_env env, napi_callback_info info) {
        if ((env == nullptr) || (info == nullptr)) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "GetContext env or info is null");
            return nullptr;
        }

        size_t argCnt = 1;
        napi_value args[1] = {nullptr};
        if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "GetContext napi_get_cb_info failed");
        }

        if (argCnt != 1) {
            napi_throw_type_error(env, NULL, "Wrong number of arguments");
            return nullptr;
        }

        napi_valuetype valuetype;
        if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
            napi_throw_type_error(env, NULL, "napi_typeof failed");
            return nullptr;
        }

        if (valuetype != napi_number) {
            napi_throw_type_error(env, NULL, "Wrong type of arguments");
            return nullptr;
        }

        int64_t value;
        if (napi_get_value_int64(env, args[0], &value) != napi_ok) {
            napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
            return nullptr;
        }

        napi_value exports;
        if (napi_create_object(env, &exports) != napi_ok) {
            napi_throw_type_error(env, NULL, "napi_create_object failed");
            return nullptr;
        }

        return exports;
    }

    void Manager::Export(napi_env env, napi_value exports) {
        if ((env == nullptr) || (exports == nullptr)) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: env or exports is null");
            return;
        }

        napi_value exportInstance = nullptr;
        if (napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: napi_get_named_property fail");
            return;
        }

        OH_NativeXComponent *nativeXComponent = nullptr;
        if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: napi_unwrap fail");
            return;
        }

        char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
        uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
        if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) !=
            OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                         "Export: OH_NativeXComponent_GetXComponentId fail");
            return;
        }

        std::string id(idStr);
        auto manager = Manager::GetInstance();
        if ((manager != nullptr) && (nativeXComponent != nullptr)) {
            manager->SetNativeXComponent(id, nativeXComponent);
            auto container = manager->GetContainer(id);
            if (container != nullptr) {
                container->RegisterCallback(nativeXComponent);
                //            container->Export(env, exports);
            }
        }
    }

    void Manager::SetNativeXComponent(std::string &id, OH_NativeXComponent *nativeXComponent) {
        if (nativeXComponent == nullptr) {
            return;
        }

        if (nativeXComponentMap_.find(id) == nativeXComponentMap_.end()) {
            nativeXComponentMap_[id] = nativeXComponent;
            return;
        }

        if (nativeXComponentMap_[id] != nativeXComponent) {
            OH_NativeXComponent *tmp = nativeXComponentMap_[id];
            // delete tmp;
            tmp = nullptr;
            nativeXComponentMap_[id] = nativeXComponent;
        }
    }

    void Manager::SetNativeNode(std::string &id, ArkUI_NodeHandle node) {
        if (node == nullptr) {
            return;
        }

        if (nativeNodeMap_.find(id) == nativeNodeMap_.end()) {
            nativeNodeMap_[id] = node;
            return;
        }

        if (nativeNodeMap_[id] != node) {
            ArkUI_NodeHandle tmp = nativeNodeMap_[id];
            // delete tmp;
            tmp = nullptr;
            nativeNodeMap_[id] = node;
        }
    }

    OH_NativeXComponent *Manager::GetNativeXComponent(const std::string &id) { return nativeXComponentMap_[id]; }

    ArkUI_NodeHandle Manager::GetNativeNode(const std::string &id) { return nativeNodeMap_[id]; }

    Container *Manager::GetContainer(std::string &id) {
        if (containerMap_.find(id) == containerMap_.end()) {
            Container *instance = Container::GetInstance(id);
            containerMap_[id] = instance;
            return instance;
        }

        return containerMap_[id];
    }
} // namespace NativeXComponentSample
